package cn.lg.soar.common.util.reflect;

import cn.lg.soar.common.util.listener.SpringUtils;
import org.springframework.util.ConcurrentReferenceHashMap;

import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * bean管理工具
 * @author luguoxiang
 * @date 2022/9/4
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class SoarBeanUtils {

    private final static Map<Class<?>, Object> CACHE = new ConcurrentReferenceHashMap<>(256);

    /**
     * 如果存在则返回，不存在则调用加载方法加载然后缓存
     * @param beanClass bean类型
     * @param loader 加载器
     * @return
     * @param <T>
     */
    public static <T>T computeBean(Class<T> beanClass, Function<Class<T>, T> loader) {
        return (T) CACHE.computeIfAbsent(beanClass, key -> {
            try{
                return SpringUtils.getBean(key);
            } catch (RuntimeException e) {
                T bean = loader.apply(beanClass);
                if (bean == null) {
                    throw e;
                }
                return bean;
            }
        });
    }

    /**
     * 如果存在则返回，不存在则调用加载方法加载然后缓存
     * @param beanClass bean类型
     * @param loader 加载器
     * @return
     * @param <T>
     */
    public static <T>T computeBean(Class<T> beanClass, Supplier<T> loader) {
        return (T) CACHE.computeIfAbsent(beanClass, key -> {
            try{
                return SpringUtils.getBean(key);
            } catch (RuntimeException e) {
                T bean = loader.get();
                if (bean == null) {
                    throw e;
                }
                return bean;
            }
        });
    }

    /**
     * 获取bean，如果不存在则调用空参构造函数构造一个实例
     * @param beanClass
     * @param <T>
     * @return
     */
    public static <T>T getBean(Class<T> beanClass) {
        return computeBean(beanClass, ReflectUtil::newInstance);
    }

    /**
     * 设置bean
     * @param bean
     */
    public static void setBean(Object bean) {
        CACHE.put(bean.getClass(), bean);
    }

}
